<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>装饰器模式弹框</title>
</head>
<style>
    #modal {
        height: 200px;
        width: 200px;
        line-height: 200px;
        position: fixed;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        border: 1px solid black;
        text-align: center;
    }
</style>

<body>
    <button id='open'>打开弹框</button>
    <button id='close'>关闭弹框</button>
</body>
<script>
    // 核心逻辑，这里采用了闭包思路来实现单例模式
    const Modal = (function () {
        let modal = null
        return function () {
            if (!modal) {
                modal = document.createElement('div')
                modal.innerHTML = '我是一个全局唯一的Modal'
                modal.id = 'modal'
                modal.style.display = 'none'
                document.body.appendChild(modal)
            }
            return modal
        }
    })()
    // 定义打开按钮
    class OpenButton {
        // 点击后展示弹框（旧逻辑）
        onClick() {
            const modal = new Modal()
            modal.style.display = 'block'
        }
    }

    // 定义按钮对应的装饰器
    class Decorator {
        // 将按钮实例传入
        constructor(open_button) {
            this.open_button = open_button
        }

        onClick() {
            this.open_button.onClick()
            // “包装”了一层新逻辑
            // 给装饰器装上整合后的功能
            this.changeButtonStatus()
        }
        // 整合各个功能
        changeButtonStatus() {
            this.changeButtonText()
            this.disableButton()
        }
        // 单一职责 将按钮禁用
        disableButton() {
            const btn = document.getElementById('open')
            btn.setAttribute("disabled", true)
        }
        // 单一职责 修改按钮内容
        changeButtonText() {
            const btn = document.getElementById('open')
            btn.innerText = '快去登录'
        }
    }
    const openButton = new OpenButton()
    // 传入model实例来实例化装饰器
    const decorator = new Decorator(openButton)
    // 后面基本上如果想用一些功能就直接使用装饰器实例就行了
    document.getElementById('open').addEventListener('click', function () {
        // openButton.onClick()
        // 此处可以分别尝试两个实例的onClick方法，验证装饰器是否生效
        decorator.onClick()
    })
    // 点击关闭按钮隐藏模态框
    document.getElementById('close').addEventListener('click', function () {
        const modal = new Modal()
        if (modal) {
            modal.style.display = 'none'
            document.getElementById('open').removeAttribute('disabled')
            document.getElementById('open').innerHTML = '打开弹框'
        }
    })
</script>

</html>